from typing import List

class Perceptron:
    def __init__(self, eta: float = 1.0, max_iter: int = 1000):
        self.eta = eta  # 步长
        self.max_iter = max_iter    # 最大迭代次数
        self._w = [0, 0, 0]     # 权重
    def fit(self, x: List[List[float]], y: List[List[int]]) -> None:
        if len(x) <= 0:     # 没有输入直接返回
            return
        times = 0
        while times < self.max_iter:    
            times += 1
            error = 0
            for xi, yi in zip(x, y):
                y_predict = self.predict(xi)    # 预测样本
                if y_predict != yi:     # 预测错误
                    error += 1
                    # 更新权重
                    for i in range(len(xi)):
                        self._w[i] += self.eta * yi * xi[i]
                    self._w[len(xi)] += self.eta * yi
                print("times : {}, xi = {}, yi = {}, y_predict = {}, _w = {}".format(times, xi, yi, y_predict, self._w))
            if error == 0:  # 找到正确的权重退出循环
                break
            
    def _predict(self, xi : List[float]) -> float:
        return sum([self._w[i] * xi[i] for i in range(len(xi))]) + self._w[len(xi)]
    
    def predict(self, xi : List[float]) -> int:
        return 1 if self._predict(xi) >= 0 else -1
    